 module Tone where 
 
 import Prelude
 
 import Data.Enum (class Enum, succ, pred)
 
 import Data.Generic.Rep (class Generic)
 
 import Data.Generic.Rep.Show (genericShow)
 
 import Data.Maybe (Maybe(..))
 
 import Data.Tuple (Tuple(..))
 
 data Tone = C | Cs | D | Ds | E | F | Fs | G | Gs | A | As | B 
 
 derive instance genericTone :: Generic Tone _ 
 
 derive instance eqTone :: Eq Tone 
 
 derive instance ordTone :: Ord Tone 
 
 instance showTone :: Show Tone where 
 
 show = genericShow
 
 instance enumTone :: Enum Tone where 
 
 succ C = Just Cs 
 
 succ Cs = Just D 
 
 succ D = Just Ds 
 
 succ Ds = Just E 
 
 succ E = Just F 
 
 succ F = Just Fs 
 
 succ Fs = Just G 
 
 succ G = Just Gs 
 
 succ Gs = Just A 
 
 succ A = Just As 
 
 succ As = Just B 
 
 succ B = Nothing 
 
 pred C = Nothing 
 
 pred Cs = Just C 
 
 pred D = Just Cs 
 
 pred Ds = Just D 
 
 pred E = Just Ds 
 
 pred F = Just E 
 
 pred Fs = Just F 
 
 pred G = Just Fs 
 
 pred Gs = Just G 
 
 pred A = Just Gs 
 
 pred As = Just A 
 
 pred B = Just As 
 
-- instance eqTone :: Eq Tone where
 
-- eq C C = true
 
-- eq C _ = false
 
-- eq Cs Cs = true
 
-- eq Cs _ = false
 
-- eq D D = true
 
-- eq D _ = false
 
-- eq Ds Ds = true
 
-- eq Ds _ = false
 
-- eq _ _ = false
 
-- instance ordTone :: Ord Tone where
 
-- compare C C = EQ
 
-- compare C _ = LT
 
-- compare Cs C = GT
 
-- compare Cs Cs = EQ
 
-- compare Cs _ = LT
 
 next :: Tone -> Tone 
 
next tone = case succ tone of 
 
 Nothing -> C 
 
 Just t -> t
 
 prev :: Tone -> Tone 
 
prev tone = case pred tone of 
 
 Nothing -> B 
 
 Just t -> t
 
 transpose :: Int -> Tone -> Tone 
 
transpose steps' tone = if steps == 0 then tone else transpose (steps + stepValue) (stepFunc tone)
 
 where 
 
 steps = steps' `mod` 12 
 
 Tuple stepFunc stepValue = if steps > 0 then Tuple next (-1) else Tuple prev 1 
 
 interval :: Tone -> Tone -> Int 
 
interval = go 0 where 
 
 go step t1 t2
 
 | t1 == t2 = step
 
 | otherwise = go (step + 1) t1 (transpose 1 t2)
 
-- TODO: genSteps :: Array Tone -> Array Int -- convert to List, pull off the head (if empty then return []) and then fold convert back to Array
 
-- TODO: genColumn :: Tone -> Array Int -> Array Tone -- convert to List, then fold and convert to Array
 
